﻿using System.Linq;
using System.Text;
using System.IO;
using AppLimit.CloudComputing.SharpBox;
using AppLimit.CloudComputing.SharpBox.StorageProvider.DropBox;
using System;
using System.Data;
using System.Windows.Forms;




namespace Librerias
{
    /// <summary>
    /// CAD que gestiona los intercambios mediante dropbox
    /// </summary>
    public class CADGestionDropbox
    {
        private CloudStorage dropbox;
        private ICloudDirectoryEntry directorio;

        private ProgressBar barra = null;
       

        /***********Conexión y desconexión con Dropbox***********/


        //Conecta con Dropbox y accede a la raiz
        public CADGestionDropbox()
        {
            //Inicia
            dropbox = new CloudStorage();
            //Configura la nube en modo Dropbox
            ICloudStorageConfiguration dropBoxConfig = CloudStorage.GetCloudConfigurationEasy(nSupportedCloudConfigurations.DropBox);

            // Accede a la cuenta de eCampus
            ICloudStorageAccessToken accessToken = dropbox.DeserializeSecurityToken(new MemoryStream(Encoding.ASCII.GetBytes("<ArrayOfKeyValueOfstringstring xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><KeyValueOfstringstring><Key>TokenProvConfigType</Key><Value>AppLimit.CloudComputing.SharpBox.StorageProvider.DropBox.DropBoxConfiguration</Value></KeyValueOfstringstring><KeyValueOfstringstring><Key>TokenCredType</Key><Value>AppLimit.CloudComputing.SharpBox.StorageProvider.DropBox.DropBoxToken</Value></KeyValueOfstringstring><KeyValueOfstringstring><Key>TokenDropBoxPassword</Key><Value>ladtuepg4mn7wk1</Value></KeyValueOfstringstring><KeyValueOfstringstring><Key>TokenDropBoxUsername</Key><Value>0qb5ayv3u6ghprp</Value></KeyValueOfstringstring><KeyValueOfstringstring><Key>TokenDropBoxAppKey</Key><Value>9t9htszdbe691c1</Value></KeyValueOfstringstring><KeyValueOfstringstring><Key>TokenDropBoxAppSecret</Key><Value>c1bxb109ogsdgs3</Value></KeyValueOfstringstring></ArrayOfKeyValueOfstringstring>")));

            // Carga la conexión
            ICloudStorageAccessToken storageToken = dropbox.Open(dropBoxConfig, accessToken);

            // Accede a raiz
            directorio = dropbox.GetFolder("/");
        }

        //Desconecta con Dropbox
        ~CADGestionDropbox()
        {
            dropbox.Close();
        }

        public static string GetFicheroFromRuta(string ruta)
        {
            string[] aux = ruta.Split('\\');


            if (aux.Length > 1) return aux[aux.Length - 1];
            else return "";

        }

        /***********Gestión de directorios***********/


        public string GetDir()
        {
            //Recorre iterativamente las carpetas hasta llegar a la raiz
            string dir = "";
            ICloudDirectoryEntry iter = directorio;

            while (iter.Parent != null)
            {
                dir = iter.Name + "/" + dir;
                iter = iter.Parent;
            }
            dir = "/" + dir;

            return dir;
        }

        /// <summary>
        /// Accede a la carpeta indicada por parámetros. Si no existe la crea.
        /// </summary>
        /// <param name="dir">Si es absoluta empieza por /, si es relativa contiene el nombre de la carpeta sin "/"</param>
        /// <returns> Si hay un fichero con su nombre, devuelve false. En otro caso, true</returns>
        public bool AccedeA(string dir)
        {
          //  string dir = direccion.Replace(" ", "");

            if (dir != GetDir())
            {
                try
                {
                    directorio = dropbox.GetFolder(ExpandeRuta(dir));
                    return true;
                }
                catch (AppLimit.CloudComputing.SharpBox.Exceptions.SharpBoxException)
                {
                    try
                    {
                        directorio = dropbox.CreateFolder(ExpandeRuta(dir));
                        return true;
                    }
                    catch (AppLimit.CloudComputing.SharpBox.Exceptions.SharpBoxException)
                    {
                        return false;
                    }
                }
            }
            else return false;
        }
        
        public bool CreaDir(string ruta)
        {
            try
            {
                directorio = dropbox.CreateFolder(ExpandeRuta(ruta));

                return directorio.Count == 0;
            }
            catch (AppLimit.CloudComputing.SharpBox.Exceptions.SharpBoxException)
            {
                return false;
            }
        }


        public DataTable getElementos()
        {
            DataTable res = new DataTable();

            res.Columns.Add("Tipo");
            res.Columns.Add("Elemento");
            
            object[] fila = new object[2];
            foreach (var elemento in directorio)
            {
                fila[0] = elemento is ICloudDirectoryEntry;
                fila[1] = elemento.Name;

                res.Rows.Add(fila);
            }

            return res;
        }


        public DataTable getElementos(string carpeta)
        {
            DataTable res = new DataTable();

            string ruta = carpeta.Replace(" ", "");
            
            res.Columns.Add("Tipo");
            res.Columns.Add("Elemento");

            AccedeA(ruta);

            object[] fila = new object[2];
            foreach (var elemento in directorio)
            {
                fila[0] = elemento is ICloudDirectoryEntry;
                fila[1] = elemento.Name;

                res.Rows.Add(fila);
            }
            
            return res;
        }

        /***********Gestión de ficheros***********/
        /*

        /// <summary>
        /// Sube el fichero a la carpeta en la que nos encontramos
        /// </summary>
        /// <param name="fichero">Ruta local del fichero a subir</param>
        /// <returns>Devuelve true si se realiza con éxito, false si ocurre error</returns>
        public bool Subir(string fichero)
        {
            try
            {
                int elementosIniciales = directorio.Count;

                dropbox.UploadFile(Environment.ExpandEnvironmentVariables(fichero), directorio);

                return elementosIniciales != directorio.Count;
            }
            catch (AppLimit.CloudComputing.SharpBox.Exceptions.SharpBoxException)
            {
                return false;
            }
        }
        */

        void UploadDownloadProgress(Object sender, FileDataTransferEventArgs e)
        {
            barra.Value = e.PercentageProgress;
            e.Cancel = false;
        }

        /// <summary>
        /// Sube el fichero a la carpeta en la que nos encontramos
        /// </summary>
        /// <param name="fichero">Ruta local del fichero a subir</param>
        /// <returns>Devuelve true si se realiza con éxito, false si ocurre error</returns>
        public bool Subir(string fichero,string ruta, ProgressBar b = null)
        {
            try
            {
                int elementosIniciales = directorio.Count;

                barra = b;
                if (barra != null)
                {
                    dropbox.UploadFile(Environment.ExpandEnvironmentVariables(fichero), ExpandeRuta(ruta), UploadDownloadProgress);
                }
                else
                {
                    dropbox.UploadFile(Environment.ExpandEnvironmentVariables(fichero), ExpandeRuta(ruta));
                }
                return true;
            }
            catch (AppLimit.CloudComputing.SharpBox.Exceptions.SharpBoxException)
            {
                return false;
            }
        }


        /// <summary>
        /// Descarga un fichero de la carpeta en la que nos encontramos
        /// </summary>
        /// <param name="fichero"></param>
        /// <param name="directorioSalida">Es la ruta SIN el nombre del fichero</param>
        public bool Descargar(string fichero, string directorioSalida, ProgressBar b = null)
        {
            try
            {
                barra = b;
                if (barra != null)
                {
                    dropbox.DownloadFile(ExpandeRuta(fichero), Environment.ExpandEnvironmentVariables(directorioSalida), UploadDownloadProgress);
                }
                else
                {
                    dropbox.DownloadFile(ExpandeRuta(fichero), Environment.ExpandEnvironmentVariables(directorioSalida));
                }
                return true;
            }
            catch (AppLimit.CloudComputing.SharpBox.Exceptions.SharpBoxException)
            {
                return false;
            }
        }



        /***********Gestión de ficheros y directorios***********/



        public bool Renombrar(string ruta, string nuevo)
        {
            
            try
            {
                return dropbox.RenameFileSystemEntry(ExpandeRuta(ruta), nuevo);
            }
            catch (AppLimit.CloudComputing.SharpBox.Exceptions.SharpBoxException)
            {
                return false;
            }
        }


        public bool Borrar(string ruta)
        {
            try
            {
                return dropbox.DeleteFileSystemEntry(ExpandeRuta(ruta));
            }
            catch (AppLimit.CloudComputing.SharpBox.Exceptions.SharpBoxException)
            {
                return false;
            }
        }

        public bool Mover(string ini, string fin)
        {
            try
            {
                return dropbox.MoveFileSystemEntry(ExpandeRuta(ini), ExpandeRuta(fin));
            }
            catch (AppLimit.CloudComputing.SharpBox.Exceptions.SharpBoxException)
            {
                return false;
            }
        }






    /************Funciones auxiliares de directorio****************/
        

        /// <summary>
        /// Comprueba la ruta. En caso de que sea relativa la expande.
        /// Si la cadena acaba en '/', elimina el último caracter. 
        /// </summary>
        /// <param name="elem"></param>
        /// <returns></returns>
        public string ExpandeRuta(string elem)
        {
            string res = elem;

            //Si la cadena acaba en '/' y no es raiz la elimina
            if (res.Length > 1 && res[res.Length - 1] == '/')
            {
                res = res.Substring(0, res.Length - 1);
            }


            //Si empieza por '/' es absoluta, si es relativa hay que expandirla
            if (res.Length > 0 && res[0] != '/')
            {
                string absoluta = GetDir();

                if (absoluta[absoluta.Length - 1] == '/')
                    res = absoluta + res;
                else
                    res = absoluta + "/" + res;
            }

            return res;
        }

        public string ElementosEnEstaCarpeta()
        {
            string res = "";
            bool esDirectorio;

            AccedeA(GetDir());

            foreach (var elemento in directorio)
            {
                esDirectorio = elemento is ICloudDirectoryEntry;

                res += (esDirectorio ? "D" : "F") + " : " + elemento.Name + "\r\n";
            }

            return res;
        }
        














        public string RutaPadre(string ruta)
        {
            string res = ExpandeRuta(ruta);
            res = res.Substring(0, res.LastIndexOf('/'));
            if (res.Length == 0) res = "/";
            
            return  res;
        }

        public string RutaCima(string ruta)
        {
            string res = ruta;
            //Si la cadena acaba en '/' y no es raiz la elimina
            if (res.Length > 1 && res[res.Length - 1] == '/')
            {
                res = res.Substring(0, res.Length - 1);
            }
            if (res.Length > 0 && res.StartsWith("/"))
            {
                res = res.Substring(res.LastIndexOf('/') + 1, res.Length - 1);
            }
            return res;
        }
    }
}